#ifndef YHAIDA_TUNNEL_H
#define YHAIDA_TUNNEL_H
#include "../../server/base/Utils.h"
#include "../../server/net/EventLoop.h"
#include "../../server/net/InetAddress.h"
#include "../../server/logging/Logging.h"
#include "../../server/net/TcpServer.h"
#include "../../server/net/TcpClient.h"
#include <memory>
#include <boost/any.hpp>

using std::placeholders::_1;
using std::placeholders::_2;
using std::placeholders::_3;

class Tunnel : public std::enable_shared_from_this<Tunnel>,
               yhaida::Utils::nocapyable
{
public:
    Tunnel(yhaida::EventLoop *loop,
           const yhaida::InetAddress &serverAddr);
        //    const yhaida::TcpConnectionPtr &serverConn);
    ~Tunnel();

    void setup();
    void connect();
    void disconnect();
    void setServerConn(const yhaida::TcpConnectionPtr& conn);
    void reset()
    {
        _serverConn.reset();
    }

    const yhaida::TcpConnectionPtr& getClient()
    {
        return _clientConn;
    }

    void setType(std::string t)
    {
        _type = std::move(t);
    }

    const std::string& getType() const 
    {
        return _type;
    }

private:
    enum ServerClient
    {
        kServer,
        kClient,
    };

private:
    void teardown();

    void onClientConnection(const yhaida::TcpConnectionPtr &conn);
    void onClientMessage(const yhaida::TcpConnectionPtr &conn,
                         yhaida::Buffer *buffer,
                         yhaida::Timestamp receiveTime);

    void onHighWaterMark(ServerClient which,
                         const yhaida::TcpConnectionPtr &conn,
                         size_t bytesToSent);
    static void onHighWaterMarkWeak(const std::weak_ptr<Tunnel> &wkTunnel,
                                    ServerClient which,
                                    const yhaida::TcpConnectionPtr &conn,
                                    size_t bytesToSent);

    void onWriteComplete(ServerClient which,
                         const yhaida::TcpConnectionPtr &conn);
    static void onWriteCompleteWeak(const std::weak_ptr<Tunnel> &wkTunnel,
                                    ServerClient which,
                                    const yhaida::TcpConnectionPtr &conn);

private:
    yhaida::TcpClient _client;//主服务器的客户端
    yhaida::TcpConnectionPtr _serverConn;//代理服务器
    yhaida::TcpConnectionPtr _clientConn;
    std::string _type;
};

typedef std::shared_ptr<Tunnel> TunnelPtr;

#endif